#pragma once

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <functional>
#include "Log.hpp"
#include "InetAddr.hpp"
#include"ThreadPool.hpp"
#include"UserManagement.hpp"

using namespace LogMudule;
using namespace ThreadPoolModule;

static const int gsocketfd = -1;
static const uint16_t dafault_prot = 8080;
static const int gsize = 1024;

using task_t = std::function<void()>;
using func_t1 = std::function<void(const InetAddr &)>;
using func_t2 = std::function<void(const int &, const std::string &)>;

class UdpServer
{
public:
    UdpServer(uint16_t prot = dafault_prot)
        : _prot(prot), _addr(prot)
    {
    }

    // 初始化服务器
    void InitServer()
    {
        // 1.创建socket文件描述符
        _socketfd = ::socket(AF_INET, SOCK_DGRAM, 0);
        if (_socketfd < 0)
        {
            LOG(LogLevel::ERROR) << "socket error...";
        }

        LOG(LogLevel::DEBUG) << "socket:" << _socketfd;

        // 2.绑定
        // 2.1初始化sockaddr_in
        // struct sockaddr_in server_addr;
        // ::bzero(&server_addr, sizeof(server_addr));
        // server_addr.sin_port = ::htons(_prot); // 端口号
        // server_addr.sin_family = AF_INET;
        // server_addr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有可用网络端口

        // 2.2.进行绑定
        int n = ::bind(_socketfd, _addr.GetAddr(), _addr.Addr_size());
        if (n < 0)
        {
            LOG(LogLevel::ERROR) << "bind error...";
        }

        LOG(LogLevel::DEBUG) << "绑定成功";
    }

    // 开始
    void Start()
    {
        LOG(LogLevel::DEBUG) << "启动服务器";
        while (true)
        {
            // 1.接受数据
            char buffer[gsize];
            struct sockaddr_in client_addr;
            socklen_t client_size = sizeof(client_addr);
            int n = ::recvfrom(_socketfd, buffer, gsize - 1, 0,  (struct sockaddr*)&client_addr, &client_size);
            if (n < 0)
            {
                LOG(LogLevel::ERROR) << "recvfrom error...";
            }

            InetAddr client_tmp(client_addr);
            buffer[n] = 0;
            std::string message(buffer);
            LOG(LogLevel::DEBUG) << "接受到的数据：" << message;

            if(message == "q")  //退出
            {
                _userdel(client_tmp);
                message = "用户退出";
            }
            else
            {
                _useraddr(client_tmp);
            }

            message = "$ " + message;
            message = client_tmp.GetIp() + message;
            LOG(LogLevel::DEBUG) << "处理后的数据：" << message;

            task_t t = std::bind(_router,_socketfd,message);
            //t();
            ThreadPool<task_t>::getInstance()->Equeue(t);
            

        }
    }

    void SetFunc(const func_t1 &useraddr, const func_t1 &userdel, const func_t2 &router)
    {
        _useraddr = useraddr;
        _userdel = userdel;
        _router = router;
    }

    ~UdpServer()
    {
        int n = ::close(_socketfd);
        (void)n;
    }

private:
    uint16_t _prot; // 端口号
    int _socketfd;  // 文件描述符
    InetAddr _addr;

    func_t1 _useraddr;
    func_t1 _userdel;
    func_t2 _router;
};
